package com.tea.modules.java8.thread.semaphore;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 使用信号量进行累加操作 <br>
 *
 * @author jaymin
 * @since 2022/2/4 18:06
 */
@Slf4j
public class CountExample {
    private static final int threadTotal = 200;
    public static final int clientTotal = 5000;
    public static long count = 0;
    private static Map<Integer,Integer> map = Maps.newHashMap();

    /**
     * 模拟5000次请求，看看最终的统计数 <br>
     * 答案是不定的,如果需要准确:
     *  Semaphore semaphore = new Semaphore(1);
     * @param args
     */
    public static void main(String[] args) {
//        countExample();
        mapExample();
    }

    private static void mapExample() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(threadTotal);
        for (int i = 0; i < clientTotal; i++) {
            final int threadNum = i;
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    func(threadNum);
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.error("exception:", e);
                }
            });
        }
        executorService.shutdown();
        log.info("size:{}", map.size());
    }

    private static void func(int threadNum) {
        map.put(threadNum,threadNum);
    }

    private static void countExample() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(threadTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (InterruptedException e) {
                    log.error("exception:", e);
                }
            });
        }
        executorService.shutdown();
        log.info("count:{}", count);
    }

    private static void add() {
        count++;
    }
}
